package it.univaq.mancoosi.injectors.systemconfiguration.managers.ubuntu;

import it.univaq.mancoosi.injectors.systemconfiguration.managers.UdevManager;
import it.univaq.mancoosi.mancoosimm.Rule;
import it.univaq.mancoosi.mancoosimm.Udev;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.emf.ecore.util.EcoreUtil;

public class UbuntuUdevManager extends UdevManager {
	
	protected Udev udev = factory.createUdev();
	ArrayList<java.io.File> rulesDirs = new  ArrayList<java.io.File>();

	public static UdevManager getInstance() {
		if (INSTANCE == null)
			INSTANCE = new UbuntuUdevManager();
		return INSTANCE;
	}	

	@Override
	public void createUdevFromSystem() {
		syncMap();
		if(UbuntuEnvironmentManager.getInstance().getEnvironment().getUdev() != null){
			this.udev.getRules().addAll(UbuntuEnvironmentManager.getInstance().getEnvironment().getUdev().getRules());
		}
		Rule newRule;
		try {			
//			ArrayList<java.io.File> rulesDirs = new  ArrayList<java.io.File>();
			rulesDirs.add(new java.io.File("/etc/udev/rules.d"));
			rulesDirs.add(new java.io.File("/lib/udev/rules.d"));

			for (int i = 0; i< rulesDirs.size(); i++) {			
				java.io.File dir = rulesDirs.get(i);
				if (dir.exists()) {
					java.io.File rules[] = dir.listFiles();
					for (int j = 0; j< rules.length; j++) {
						java.io.File rule = rules[j];
						if (rule.isFile() && rule.getName().endsWith(".rules")) {
							if (!exists(rule.getName())) {
								newRule = factory.createRule();
								newRule.setFile(UbuntuFileSystemManager.getInstance()
										.createFile(rule.getPath()));
								newRule.setName(rule.getName());
								this.ruleMap.put(rule.getName(), newRule);
								this.udev.getRules().add(newRule);
							}
						}
					}
				}
			}
			UbuntuEnvironmentManager.getInstance().getEnvironment().setUdev(this.udev);
			
		} catch (Exception err) {
			err.printStackTrace();
		}   
	}

	@Override
	public void synchronize() throws IOException {
		createUdevFromSystem();
		
		int rulesInTheSystem = countRules();
		
		if(((this.ruleMap.size()) != rulesInTheSystem)){	

			Iterator<Rule> iterator = this.ruleMap.values().iterator();
			while (iterator.hasNext()) {
				Rule curr = iterator.next();
				if (isMissingRuleInTheSystem(curr.getName())) {
					this.ruleMap.remove(curr);
					EcoreUtil.delete(curr);
					UbuntuFileSystemManager.getInstance().deleteFile(curr.getFile());
				}
			}
		}
	}
	
	public int countRules() throws IOException {
		int rulesNumber = 0;
		
		for (int i = 0; i< rulesDirs.size(); i++) {			
			java.io.File dir = rulesDirs.get(i);
			if (dir.exists()) {
				java.io.File rules[] = dir.listFiles();
				for (int j = 0; j< rules.length; j++) {
					java.io.File rule = rules[j];
					if (rule.isFile() && rule.getName().endsWith(".rules")) {
						rulesNumber++;
					}
				}
			}
		}
		return rulesNumber;
	}
	
	public boolean isMissingRuleInTheSystem (String ruleName) {
		boolean file1 = false;
		boolean file2 = false;
		if(UbuntuFileSystemManager.getInstance().getFile("/etc/udev/rules.d/" + ruleName) != null){
			file1 = UbuntuFileSystemManager.getInstance().getFile("/etc/udev/rules.d/" + ruleName).isIsMissing();
		}
		if(UbuntuFileSystemManager.getInstance().getFile("/lib/udev/rules.d/" + ruleName) != null){
			file2 = UbuntuFileSystemManager.getInstance().getFile("/lib/udev/rules.d/" + ruleName).isIsMissing();
		}
		
		return (file1 || file2);
	}

	@Override
	public Boolean exists(String ruleName) {
		return this.ruleMap.containsKey(ruleName);
	}

}
